// interfaces/interfaceprocessor/FilterProcessor.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// {java interfaces.interfaceprocessor.FilterProcessor}
package com.lmq.interfaces.interfaceprocessor;
import com.lmq.interfaces.filters.*;

class FilterAdapter implements Processor {
  Filter filter;
  FilterAdapter(Filter filter) {
    this.filter = filter;
  }
  @Override
  public String name() { return filter.name(); }
  @Override
  public Waveform process(Object input) {
    return filter.process((Waveform)input);
  }
}

public class FilterProcessor {
  public static void main(String[] args) {
    Waveform w = new Waveform();
    Applicator.apply(
      new FilterAdapter(new LowPass(1.0)), w);
    Applicator.apply(
      new FilterAdapter(new HighPass(2.0)), w);
    Applicator.apply(
      new FilterAdapter(new BandPass(3.0, 4.0)), w);
  }
}
/* Output:
Using Processor LowPass
Waveform 0
Using Processor HighPass
Waveform 0
Using Processor BandPass
Waveform 0
*/

/**
 * in this approach to Adapter, the FilterAdapter constructor takes the interface
 * you have Filter and produces an object that has the Processor interface you need.
 * You might also notice delegation in the FilterAdapter class.
 * Covariance allows us to produce a Waveform from process() rather than
 * just an Object.
 * Decoupling interface from implementation allows an interface to be
 * applied to multiple different implementations, and thus your code is more reusable.
 * Combing Multiple interfaces
 * Because an interface has no implementation at all that is , there is
 * no storage associated with an interface there's nothing to prevent many interfaces from being combined.
 * This is valuable because there are times when you want to say, "An x
 * is an a and a b and a c."
 * In a derived class, you aren't forced to have a base class that is either abstract or "concrete"(that is , one with no abstract
 * methods) if you do inherit from a non-interface, you can inherit from only one.All the rest of the base elemnts must be interfaces.You palce all the interface names after the implements keyword and seprate them
 * with commas.You can have as many interfaces as you want.you can upcast to each
 * interface, because each interface is an independent type.The following example shows
 * a concrete class combine with several interfaces to produce a new class:
 */
